package cn.starrysky108.simpleerp.core.base;

import cn.starrysky108.simpleerp.core.constant.Constants;
import cn.starrysky108.simpleerp.pub.request.OrderListRequest;
import cn.starrysky108.simpleerp.pub.request.PageParam;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import io.swagger.annotations.ApiOperation;
import org.apache.tomcat.util.digester.ArrayStack;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Carl Lee
 */
public abstract class BaseController<S extends IService<T>, T extends BaseEntity> {
    protected final HttpServletRequest request;
    protected final HttpServletResponse response;
    protected final S service;

    protected BaseController(HttpServletRequest request, HttpServletResponse response, S service) {
        this.request = request;
        this.response = response;
        this.service = service;
    }

    @GetMapping("/{id}")
    @ApiOperation("分页获取单条数据")
    public Object getOne(@PathVariable Long id) {
        Assert.notNull(id, "参数为空");
        return service.getById(id);
    }

    @ApiOperation("分页获取全部数据")
    public Object list(@RequestBody PageParam param) {
        Page<T> page;
        if (ObjectUtils.isEmpty(param)) {
            page = new Page<>(Constants.DEFAULT_PAGE, Constants.DEFAULT_LIMIT);
        } else {
            page = new Page<>(param.getCurrent(), param.getSize());
        }
        service.page(page);
        return page;
    }

    /**
     * 分页显示不同订单状态
     *
     * @param param 订单查询参数
     */
    @GetMapping()
    @ApiOperation("分页显示不同订单状态的数据")
    public Object list(OrderListRequest param) {
        Page<T> page = new Page<>(param.getCurrent(), param.getSize());
        QueryWrapper<T> query = Wrappers.query();

        if (param.isAsc()) {
            page.addOrder(OrderItem.ascs(param.getColumn().split(",")));
        } else {
            page.addOrder(OrderItem.descs(param.getColumn().split(",")));
        }
        if (!ObjectUtils.isEmpty((param.getStatus()))) {
            query.eq("status", param.getStatus());
        }
        //时间范围筛选
        if (StringUtils.hasText(param.getDuration())) {
            String[] duration = param.getDuration().split("/");
            int len = 2;
            if (duration.length == len) {
                final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_FORMAT);
                LocalDateTime start = LocalDate.parse(duration[0], formatter).atStartOfDay();
                LocalDateTime end = LocalDate.parse(duration[1], formatter).atStartOfDay();
                query.between("gmt_create", start, end);
            }
        }
        return service.page(page, query);
    }

    @PostMapping
    @ApiOperation("增加一条记录")
    public Object add(@Validated @RequestBody T t) {
        Assert.notNull(t, "解析参数失败，请检查传递的参数是否符合要求");
        boolean success = service.save(t);
        if (success) {
            return BaseResponseEntity.success("数据保存成功");
        }
        return BaseResponseEntity.failure("数据保存失败");
    }

    @DeleteMapping("/{id}")
    @ApiOperation("删除一条记录")
    public Object delete(@PathVariable Long id) {
        Assert.notNull(id, "解析参数失败，请检查传递的参数是否符合要求");
        boolean success = service.removeById(id);
        if (success) {
            return BaseResponseEntity.success("数据删除成功");
        }
        return BaseResponseEntity.failure("数据删除失败");
    }

    @PutMapping("/{id}")
    @ApiOperation("修改一条记录")
    public Object update(@PathVariable Long id, @RequestBody T t) {
        Assert.notNull(t, "解析参数失败，请检查传递的参数是否符合要求");
        Assert.notNull(t.getId(), "参数中必须包含id字段");
        Assert.isTrue(id.equals(t.getId()), "参数错误，id不符合要求");
        boolean success = service.updateById(t);
        if (success) {
            return BaseResponseEntity.success("数据修改成功");
        }
        return BaseResponseEntity.failure("数据修改失败");
    }

    @PatchMapping
    @ApiOperation("批量修改")
    public Object updateBatch(@Validated @RequestBody ArrayList<T> list) {
        Assert.notNull(list, "解析参数失败，请检查传递的参数是否符合要求");
        List<Long> errorIds = new ArrayStack<>();
        list
                .forEach(t -> {
                            if (!ObjectUtils.isEmpty(t.getId())) {
                                if (!service.updateById(t)) {
                                    errorIds.add(t.getId());
                                }
                            }

                        }
                );
        if (ObjectUtils.isEmpty(errorIds)) {
            return BaseResponseEntity.success("批量修改全部成功");
        }
        return BaseResponseEntity.failure(-1, "部分数据修改失败", errorIds);
    }

}
